package web

import (
	"fmt"
	"jgt-oper/src/bll"
	"jgt-oper/src/context"
	"jgt-oper/src/schema"
	"jgt-oper/src/util"
	"strings"
	"time"
)

// Enterprise 企业管理
type Enterprise struct {
	EnterpriseBll     *bll.Enterprise     `inject:""`
	EnterHistoryBll   *bll.EnterHistory   `inject:""`
	ParkBll           *bll.Park           `inject:""`
	EnterpriseParkBll *bll.EnterprisePark `inject:""`
}

// QueryPage 查询分页数据
func (a *Enterprise) QueryPage(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.QueryPage", "企业管理-查询分页数据")

	pageIndex, pageSize := ctx.GetPageIndex(), ctx.GetPageSize()

	params := schema.EnterpriseQueryParam{
		Name:               ctx.Query("name"),
		Contacts:           ctx.Query("contacter"),
		ContactTel:         ctx.Query("contact_tel"),
		Address:            ctx.Query("address"),
		EntryTimeStart:     util.UnixToStart(util.S(ctx.Query("entry_time_start")).Int64()),
		EntryTimeEnd:       util.UnixToEnd(util.S(ctx.Query("entry_time_end")).Int64()),
		MigrationTimeStart: util.UnixToStart(util.S(ctx.Query("migration_time_start")).Int64()),
		MigrationTimeEnd:   util.UnixToEnd(util.S(ctx.Query("migration_time_end")).Int64()),
		IsHot:              util.S(ctx.Query("is_hot")).Int(),
		Status:             util.S(ctx.Query("status")).Int(),
	}

	if v := ctx.Query("category"); v != "" {
		params.Category = strings.Split(v, ",")
	}

	total, items, err := a.EnterpriseBll.QueryPage(&params, pageIndex, pageSize)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}

	category, err := a.EnterpriseBll.QueryCategory()
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}

	for i, item := range items {
		for _, c := range category {
			if c["record_id"] == item.Category {
				items[i].Category = c["name"]
				break
			}
		}
	}

	result := map[string]interface{}{
		"list": items,
		"pagination": map[string]interface{}{
			"total":    total,
			"current":  pageIndex,
			"pageSize": pageSize,
		},
	}

	return ctx.ResSuccess(result)
}

// QuerySelect 查询选择数据
func (a *Enterprise) QuerySelect(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.QuerySelect", "企业管理-查询条目详情")
	items, err := a.EnterpriseBll.QuerySelect(ctx.Query("name"))
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	return ctx.ResSuccess(items)
}

// QueryCategory 查询类别数据
func (a *Enterprise) QueryCategory(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.QueryCategory", "企业管理-查询企业类别信息")
	items, err := a.EnterpriseBll.QueryCategory()
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	return ctx.ResSuccess(items)
}

// QueryEnterpriseMark 查询企业标识
func (a *Enterprise) QueryEnterpriseMark(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.QueryEnterpriseMark", "企业管理-查询企业标识信息")
	items, err := a.EnterpriseBll.QueryEnterpriseMark()
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	return ctx.ResSuccess(items)
}

// Get 精确查询数据
func (a *Enterprise) Get(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.Get", "企业管理-查询企业信息详情")
	enterpriseID := ctx.Param("id")
	item, err := a.EnterpriseBll.Get(enterpriseID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	//	查询企业的门牌
	entrancePark, err := a.EnterpriseParkBll.Get(enterpriseID)
	item.BuildingNodeID = entrancePark.Nodes
	return ctx.ResSuccess(item)
}

//	TODO	门牌的子节点需要遍历出来，写入门牌历史

// Create 创建数据
func (a *Enterprise) Create(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.Create", "企业管理-创建数据")
	var item schema.Enterprise
	if err := ctx.ParseJSON(&item); err != nil {
		return ctx.ResErrBadRequest(err)
	}
	//	初始化相关信息
	item.IsPanel = 0
	item.MigrationTime = 0
	item.Status = 1
	item.ID = 0
	item.RecordID = util.UUID()
	item.Creator = ctx.GetUserID()
	item.Created = time.Now().Unix()
	item.Deleted = 0
	nodeIDArray := item.BuildingNodeID
	//	去除门牌信息，企业基本信息表不再储存门牌信息
	item.BuildingNodeID = nil
	//	创建存储企业基本信息
	err := a.EnterpriseBll.Create(&item)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	//	创建企业和入驻门牌对应关系
	enterprisePark := new(schema.EnterprisePark)
	enterprisePark.EnterpriseID = item.RecordID
	enterprisePark.Nodes = nodeIDArray
	enterprisePark.EntrancesFrozen = nil
	enterprisePark.Creator = item.Creator
	enterprisePark.Created = item.Created
	enterprisePark.Deleted = 0
	//	存储企业和入驻门牌对应关系
	err = a.EnterpriseParkBll.Create(enterprisePark)
	if err != nil {
		fmt.Println("err:--->", err)
		return ctx.ResErrInternalServer(err)
	}
	//	遍历门牌
	for _, value := range nodeIDArray {
		//	储存门牌历史
		insertItem := new(schema.EnterpriseParkHistory)
		insertItem.ParkID = value
		insertItem.Created = item.Created
		insertItem.Creator = item.Creator
		insertItem.EnterpriseID = item.RecordID
		insertItem.Operate = "迁入"
		insertItem.Memo = "企业入驻"
		err := a.EnterHistoryBll.InsertItem(insertItem)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}

		//	修改建筑节点的租赁状态信息
		info := map[string]interface{}{"lease_status": 10}
		err = a.ParkBll.UpdateLeaseStatus(value, info)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
	}
	return ctx.ResOK()
}

// Update 更新数据
func (a *Enterprise) Update(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.Update", "企业管理-更新数据")
	//	获取更新post参数
	item := new(schema.Enterprise)
	if err := ctx.ParseJSON(item); err != nil {
		return ctx.ResErrBadRequest(err)
	}
	item.Creator = ctx.GetUserID()
	//	企业id
	enterpriseID := ctx.Param("id")
	//	获取企业和门牌对应关系
	oldEnterprisePark, err := a.EnterpriseParkBll.Get(enterpriseID)
	if err != nil {
		return err
	}
	//	获取企业基本信息
	oldEnterprise, err := a.EnterpriseBll.Get(enterpriseID)
	if err != nil {
		return err
	}
	//	使用map集合运算出，减少、增加的门牌节点
	setMap := make(map[string]int)
	//bMap := make(map[string]int)
	nodeAdded := make([]string, 0)
	nodeRemoved := make([]string, 0)
	//	集合中 先放入之前的门牌，后放入新提交的门牌
	for _, nodeOld := range oldEnterprisePark.Nodes {
		setMap[nodeOld] = 1
	}
	for _, nodeNew := range item.BuildingNodeID {
		setMap[nodeNew] = 2
	}
	//	筛选出减少的门牌
	for node, code := range setMap {
		if code == 1 {
			nodeRemoved = append(nodeRemoved, node)
		}
	}
	//	再次放入 之前的门牌
	for _, nodeOld := range oldEnterprisePark.Nodes {
		setMap[nodeOld] = 1
	}
	//	筛选出 增加的门牌
	for node, code := range setMap {
		if code == 2 {
			nodeAdded = append(nodeAdded, node)
		}
	}
	//	对企业的门牌进行更新
	if len(nodeAdded) > 0 { //	添加门牌
		err = a.EnterpriseParkBll.AddNodes(enterpriseID, nodeAdded)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
	}
	if len(nodeRemoved) > 0 { //	减少门牌
		err = a.EnterpriseParkBll.DeleteNodes(enterpriseID, nodeRemoved)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
	}

	//	针对减少、增加的门牌进行更新门牌历史信息
	for _, value := range nodeAdded {
		insertItem := new(schema.EnterpriseParkHistory)
		insertItem.ParkID = value
		insertItem.Created = time.Now().Unix()
		insertItem.Creator = item.Creator
		insertItem.EnterpriseID = item.RecordID
		insertItem.Operate = "迁入"
		insertItem.Memo = "企业信息更新:添加门牌"
		err = a.EnterHistoryBll.InsertItem(insertItem)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}

		//修改建筑节点的租赁状态信息
		infoNode := map[string]interface{}{"lease_status": 10}
		err = a.ParkBll.UpdateLeaseStatus(value, infoNode)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
	}
	for _, value := range nodeRemoved {
		insertItem := new(schema.EnterpriseParkHistory)
		insertItem.ParkID = value
		insertItem.Created = time.Now().Unix()
		insertItem.Creator = item.Creator
		insertItem.EnterpriseID = item.RecordID
		insertItem.Operate = "迁出"
		insertItem.Memo = "企业信息更新:删除门牌"
		err = a.EnterHistoryBll.InsertItem(insertItem)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}

		//修改建筑节点的租赁状态信息
		infoNode := map[string]interface{}{"lease_status": 20}
		err = a.ParkBll.UpdateLeaseStatus(value, infoNode)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
	}
	//	使用map集合 计算出不变的门牌
	temMap := make(map[string]int)
	notChangedNodes := make([]string, 0)
	for _, nodeOld := range oldEnterprisePark.Nodes {
		temMap[nodeOld] = 1
	}
	for _, nodeRemoved := range nodeRemoved {
		temMap[nodeRemoved] = 2
	}
	for node, code := range temMap {
		if code == 1 {
			notChangedNodes = append(notChangedNodes, node)
		}
	}
	//	门牌没有变化的 如果企业名称变更，门牌历史信息中记录"企业名称变更"
	if oldEnterprise.Name != item.Name {
		for _, value := range notChangedNodes {
			insertItem := new(schema.EnterpriseParkHistory)
			insertItem.ParkID = value
			insertItem.Created = time.Now().Unix()
			insertItem.Creator = item.Creator
			insertItem.EnterpriseID = item.RecordID
			insertItem.Operate = "变更"
			insertItem.Memo = "企业信息更新:企业名称变更"
			err = a.EnterHistoryBll.InsertItem(insertItem)
			if err != nil {
				return ctx.ResErrInternalServer(err)
			}
		}
	}
	//	****
	info := util.StructToMap(item)
	delete(info, "status")
	delete(info, "is_panel")
	delete(info, "id")
	delete(info, "record_id")
	delete(info, "creator")
	delete(info, "created")
	delete(info, "deleted")
	delete(info, "building_node_id")
	err = a.EnterpriseBll.Update(ctx.Param("id"), info)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	return ctx.ResOK()
}

// Migration 企业迁出
func (a *Enterprise) Migration(ctx *context.Context) error {
	ctx.WriteOperateLog("Enterprise.Migration", "企业管理-企业迁出")
	operatorID := ctx.GetUserID()
	enterpriseID := ctx.Param("id")
	//	****
	//	更新状态字段 为迁出状态
	info := map[string]interface{}{
		"status":         2,
		"migration_time": time.Now().Unix(),
	}
	err := a.EnterpriseBll.Update(enterpriseID, info)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	//	门牌历史添加 迁出记录
	//	现获取企业的门牌
	item, err := a.EnterpriseParkBll.Get(enterpriseID)
	//	删除企业门牌
	err = a.EnterpriseParkBll.DeleteNodes(enterpriseID, item.Nodes)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	//	遍历门牌:更新门牌历史和门牌租赁状态
	for _, node := range item.Nodes {
		//	添加门牌迁出历史记录
		insertItem := new(schema.EnterpriseParkHistory)
		insertItem.ParkID = node
		insertItem.Created = time.Now().Unix()
		insertItem.Creator = operatorID
		insertItem.EnterpriseID = enterpriseID
		insertItem.Operate = "迁出"
		insertItem.Memo = "企业信息更新:删除门牌"
		err = a.EnterHistoryBll.InsertItem(insertItem)
		if err != nil {
			return err
		}

		//	修改建筑节点的租赁状态信息
		info := map[string]interface{}{"lease_status": 20}
		err = a.ParkBll.UpdateLeaseStatus(node, info)
		if err != nil {
			return err
		}
	}
	return ctx.ResOK()
}
